package xxl.robotlegs.extensions.commandcenter.impl 
{
	import flash.utils.Dictionary;
	import xxl.robotlegs.extensions.commandcenter.api.ICommandMapping;
	import xxl.robotlegs.extensions.commandcenter.api.ICommandMappingList;
	import xxl.robotlegs.extensions.commandcenter.api.ICommandTrigger;
	import xxl.robotlegs.framework.api.ILogger;
	/**
	 * ...
	 * @author XXL
	 */
	public class CommandMappingList implements ICommandMappingList
	{
		private var _trigger:ICommandTrigger;
		private var _processors:Array;
		private var _logger:ILogger;
		private var _sorted:Boolean;
		private var _compareFunction:Function;
		private var _mappings:Vector.<ICommandMapping> = new Vector.<ICommandMapping>();
		private const _mappingsByCommand:Dictionary = new Dictionary();
		
		public function CommandMappingList(trigger:ICommandTrigger, processors:Array, logger:ILogger = null) 
		{
			_trigger = trigger;
			_processors = processors;
			_logger = logger;
		}
		
		private function sortMappings():void
		{
			if (_compareFunction != null)
			{
				_mappings = _mappings.sort(_compareFunction);
			}
			_sorted = true;
		}
		
		private function applyProcessors(mapping:ICommandMapping):void
		{
			for each(var processor:Function in _processors)
			{
				processor(mapping);
			}
		}
		
		private function overwriteMapping(oldMapping:ICommandMapping, newMapping:ICommandMapping):void
		{
			_logger && _logger.warn("{0} 已经映射了一个 {1}了", [_trigger, oldMapping]);
			deleteMapping(oldMapping);
			storeMapping(newMapping);
		}
		
		private function deleteMapping(mapping:ICommandMapping):void
		{
			delete _mappingsByCommand[mapping.commandClass];
			_mappings.splice(_mappings.indexOf(mapping), 1);
			_logger && _logger.debug("{0} 取消映射 {1}", [_trigger, mapping]);
		}
		
		private function storeMapping(mapping:ICommandMapping):void
		{
			_mappingsByCommand[mapping.commandClass] = mapping;
			_mappings.push(mapping);
			_logger && _logger.debug("{0} 映射 {1}", [_trigger, mapping]);
		}
		
		/* INTERFACE xxl.robotlegs.extensions.commandcenter.api.ICommandMappingList */
		
		public function withSortFunction(sorter:Function):ICommandMappingList 
		{
			_sorted = false;
			_compareFunction = sorter;
			return this;
		}
		
		public function getList():Vector.<ICommandMapping> 
		{
			_sorted || sortMappings();
			return _mappings.concat();
		}
		
		public function addMapping(mapping:ICommandMapping):void 
		{
			_sorted = false;
			applyProcessors(mapping);
			const oldMapping:ICommandMapping = _mappingsByCommand[mapping.commandClass];
			if (oldMapping)
			{
				overwriteMapping(oldMapping, mapping);
			}
			else
			{
				storeMapping(mapping);
				_mappings.length == 1 && _trigger.activate();
			}
		}
		
		public function removeMapping(mapping:ICommandMapping):void 
		{
			if (_mappingsByCommand[mapping.commandClass])
			{
				deleteMapping(mapping);
				_mappings.length == 0 && _trigger.deactivate();
			}
		}
		
		public function removeMappingFor(commandClass:Class):void 
		{
			const mapping:ICommandMapping = _mappingsByCommand[commandClass];
			mapping && removeMapping(mapping);
		}
		
		public function removeAllMappings():void 
		{
			if (_mappings.length > 0)
			{
				for (var i:int = _mappings.length; i--; )
				{
					deleteMapping(_mappings[i]);
				}
				_trigger.deactivate();
			}
		}
		
	}

}